<template>
  <div class="news-detail-container">
    <!-- 面包屑导航 -->
    <el-breadcrumb separator="/" class="breadcrumb">
      <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item :to="{ path: '/news' }">新闻中心</el-breadcrumb-item>
      <el-breadcrumb-item>新闻详情</el-breadcrumb-item>
    </el-breadcrumb>

    <!-- 新闻主体 -->
    <div class="news-main" v-if="newsData">
      <!-- 新闻标题区 -->
      <div class="news-header">
        <h1 class="news-title">{{ newsData.title }}</h1>
        <div class="news-meta">
          <span class="news-time">
            <el-icon><Clock /></el-icon>
            {{ formatDate(newsData.publishTime) }}
          </span>
          <span class="news-author">
            <el-icon><User /></el-icon>
            {{ newsData.author || '本站编辑' }}
          </span>
          <span class="news-views">
            <el-icon><View /></el-icon>
            阅读量: {{ newsData.views || 0 }}
          </span>
        </div>
      </div>

      <!-- 新闻封面图 -->
      <div class="news-cover" v-if="newsData.coverImage">
        <el-image
            :src="newsData.coverImage"
            :preview-src-list="[newsData.coverImage]"
            fit="cover"
        />
      </div>

      <!-- 新闻正文 -->
      <div class="news-content" v-html="newsData.content"></div>

      <!-- 图片画廊 -->
      <div class="news-gallery" v-if="newsData.images && newsData.images.length">
        <h3 class="gallery-title">相关图片</h3>
        <el-row :gutter="20">
          <el-col
              v-for="(img, index) in newsData.images"
              :key="index"
              :xs="24" :sm="12" :md="8"
          >
            <el-image
                :src="img.url"
                :alt="img.caption || '新闻配图'"
                :preview-src-list="newsData.images.map(i => i.url)"
                class="gallery-image"
            >
              <template #error>
                <div class="image-error">
                  <el-icon><Picture /></el-icon>
                  <span>图片加载失败</span>
                </div>
              </template>
            </el-image>
            <p class="image-caption" v-if="img.caption">{{ img.caption }}</p>
          </el-col>
        </el-row>
      </div>

      <!-- 标签和分享 -->
      <div class="news-footer">
        <div class="news-tags">
          <el-tag
              v-for="(tag, index) in mappedTags"
              :key="index"
              size="small"
              :type="tagTypes[index % tagTypes.length]"
          >
            {{ tag }}
          </el-tag>
        </div>
        <div class="news-share">
          <span>分享至：</span>
          <el-button type="primary" plain circle size="small" @click="shareNews">
            <el-icon><Share /></el-icon>
          </el-button>
          <el-button type="success" plain circle size="small">
            <el-icon><ChatDotRound /></el-icon>
          </el-button>
          <el-button type="warning" plain circle size="small">
            <el-icon><Star /></el-icon>
          </el-button>
        </div>
      </div>
    </div>

    <!-- 相关新闻推荐 -->
    <div class="related-news" v-if="relatedNews.length">
      <h3 class="related-title">相关推荐</h3>
      <el-row :gutter="20">
        <el-col
            v-for="(item, index) in relatedNews"
            :key="index"
            :xs="24" :sm="12" :md="8"
        >
          <el-card shadow="hover" class="related-card" @click="goToNews(item.relationalNewsId)">
            <el-image
                :src="item.cover"
                class="related-cover"
                fit="cover"
            />
            <div class="related-info">
              <h4>{{ item.title }}</h4>
              <p class="related-time">{{ formatDate(item.publishTime) }}</p>
            </div>
          </el-card>
        </el-col>
      </el-row>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, watch, nextTick } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import {
  Clock,
  User,
  View,
  Picture,
  Share,
  ChatDotRound,
  Star
} from '@element-plus/icons-vue'
import { getNewsInfo, getRelationalNewsInfo } from '@/api/news'
import { dictType } from '@/api/dict'
import { ElMessage } from "element-plus"

const router = useRouter()
const route = useRoute()
const tagTypes = ['', 'success', 'info', 'warning', 'danger']

const newsData = ref(null)
const relatedNews = ref([])
const dictList = ref([])
const mappedTags = ref([])

// 🎯 新增：请求控制标志位
const isLoading = ref(false)
const hasLoadedDict = ref(false)
const lastRequestId = ref(null) // 记录最后一次请求的ID

// 分享功能保持不变
const shareNews = async () => {
  const title = newsData.value?.title || '新闻详情'
  const text = newsData.value?.content || ''
  const url = window.location.href

  const shareData = { title, text, url }

  if (navigator.share) {
    try {
      if (/iPad|iPhone|iPod/.test(navigator.userAgent) && !navigator.canShare?.({ text })) {
        delete shareData.text
      }
      await navigator.share(shareData)
      console.log('分享成功')
    } catch (err) {
      console.error('分享取消或失败', err)
    }
  } else if (navigator.clipboard) {
    try {
      await navigator.clipboard.writeText(url)
      ElMessage.success('链接已复制到剪贴板')
    } catch (err) {
      console.error('复制失败', err)
      ElMessage.error('复制失败，请手动复制链接')
    }
  } else {
    const tempInput = document.createElement('input')
    tempInput.value = url
    document.body.appendChild(tempInput)
    tempInput.select()
    document.execCommand('copy')
    document.body.removeChild(tempInput)
    ElMessage.success('链接已复制到剪贴板')
  }
}

const formatDate = (dateString) => {
  const date = new Date(dateString)
  return `${date.getFullYear()}年${date.getMonth() + 1}月${date.getDate()}日`
}

const goToNews = (id) => {
  router.push(`/news/${id}`)
}

// 🎯 优化：字典只加载一次
const loadDict = async () => {
  if (hasLoadedDict.value) return

  try {
    hasLoadedDict.value = true
    const res = await dictType('kiku_news_tag')
    dictList.value = res.data.data || []
  } catch (error) {
    console.error('获取字典失败:', error)
    hasLoadedDict.value = false // 失败时重置标志位
  }
}

const mapTags = () => {
  if (!newsData.value?.tags) {
    mappedTags.value = []
    return
  }
  mappedTags.value = newsData.value.tags.map(tagValue => {
    const dictItem = dictList.value.find(d => d.dictValue === tagValue)
    return dictItem ? dictItem.dictLabel : tagValue
  })
}

// 🎯 优化：新闻详情加载（防重复请求）
const loadNews = async (id) => {
  if (!id || isLoading.value || lastRequestId.value === id) {
    return // 防止重复请求同一ID
  }

  isLoading.value = true
  lastRequestId.value = id // 记录当前请求ID

  try {
    const res = await getNewsInfo(id)
    newsData.value = res.data.data
    mapTags()

    const relRes = await getRelationalNewsInfo(id)
    relatedNews.value = relRes.data.data || []
  } catch (error) {
    console.error('获取新闻详情失败:', error)
    // 错误时重置lastRequestId，允许重试
    if (lastRequestId.value === id) {
      lastRequestId.value = null
    }
  } finally {
    isLoading.value = false
  }
}

// 🎯 优化：使用防抖函数控制watch触发频率[6,7,8](@ref)
const debounce = (func, wait) => {
  let timeout = null
  return function (...args) {
    clearTimeout(timeout)
    timeout = setTimeout(() => func.apply(this, args), wait)
  }
}

// 创建防抖版本的loadNews
const debouncedLoadNews = debounce(loadNews, 100)

// 🎯 优化onMounted：确保执行顺序
onMounted(async () => {
  await loadDict() // 先加载字典

  // 使用nextTick确保DOM更新完成后再加载新闻
  await nextTick()

  if (route.params.id) {
    await loadNews(route.params.id)
  }
})

// 🎯 优化watch监听：使用防抖和控制条件[1,4](@ref)
watch(
    () => route.params.id,
    async (newId, oldId) => {
      // 只有当ID真正发生变化时才加载
      if (newId && newId !== oldId) {
        await debouncedLoadNews(newId)
      }
    },
    { immediate: false } // 禁止立即执行，避免与onMounted重复
)
</script>


<style scoped>
.news-detail-container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px;
}

.breadcrumb {
  margin-bottom: 20px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--el-border-color-light);
}

.news-main {
  background-color: #fff;
  padding: 30px;
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}

.news-header {
  margin-bottom: 30px;
  text-align: center;
}

.news-title {
  font-size: 28px;
  margin-bottom: 15px;
  color: #333;
  line-height: 1.4;
}

.news-meta {
  display: flex;
  justify-content: center;
  gap: 20px;
  color: #666;
  font-size: 14px;
  margin-bottom: 20px;
}

.news-meta .el-icon {
  margin-right: 5px;
}

.news-cover {
  margin-bottom: 30px;
}

.news-cover .el-image {
  width: 100%;
  max-height: 500px;
  border-radius: 4px;
}

.news-content {
  line-height: 1.8;
  font-size: 16px;
  color: #333;
  margin-bottom: 40px;
}

.news-content :deep(p) {
  margin-bottom: 20px;
  text-indent: 2em;
}

.gallery-title {
  font-size: 20px;
  margin: 40px 0 20px;
  color: #333;
  border-left: 4px solid var(--el-color-primary);
  padding-left: 10px;
}

.gallery-image {
  width: 100%;
  height: 200px;
  border-radius: 4px;
  overflow: hidden;
  position: relative;
}

.gallery-image {
  width: 100%;
  height: 200px;
  border-radius: 4px;
  overflow: hidden;
  position: relative;
}

/* 使用深度穿透确保作用到 el-image 内部 img 元素 */
.gallery-image :deep(img) {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.image-error {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: #999;
}

.news-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 40px;
  padding-top: 20px;
  border-top: 1px solid var(--el-border-color-light);
}

.news-tags {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

.news-share {
  display: flex;
  align-items: center;
  gap: 10px;
}

.related-news {
  margin-top: 50px;
}

.related-title {
  font-size: 22px;
  margin-bottom: 30px;
  padding-bottom: 15px;
  border-bottom: 1px solid var(--el-border-color-light);
}

.related-card {
  margin-bottom: 20px;
  cursor: pointer;
  transition: transform 0.3s;
}

.related-card:hover {
  transform: translateY(-5px);
}

.related-cover {
  width: 100%;
  height: 180px;
}

.related-info {
  padding: 15px;
}

.related-info h4 {
  font-size: 16px;
  margin-bottom: 10px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.related-time {
  color: #666;
  font-size: 14px;
}

@media (max-width: 768px) {
  .news-main {
    padding: 20px;
  }

  .news-title {
    font-size: 22px;
  }

  .news-meta {
    flex-direction: column;
    gap: 8px;
    align-items: center;
  }

  .news-footer {
    flex-direction: column;
    gap: 20px;
  }

  .news-share {
    width: 100%;
    justify-content: center;
  }
}
</style>
